package com.example.demo.controller;

import com.example.demo.factory.IdGeneratorFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author C12645
 * @description
 * @date 2021/10/14 8:08
 **/
@RestController
public class TestController {

    @Autowired
    private IdGeneratorFactory idGeneratorFactory;

    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping(value = "/getId/{key}", method = RequestMethod.GET)
    public Long getId(@PathVariable("key") String key) {
        long generate = idGeneratorFactory.generate(key, IdGeneratorFactory.getTodayEndTime());
        return generate;
    }

    @RequestMapping(value = "/getIdByToday/{key}", method = RequestMethod.GET)
    public String getIdByToday(@PathVariable("key") String key) {
        String id = idGeneratorFactory.generateIdByToday(key, 6);
        return id;
    }

    /**
     * 获取递增的序列号
     *
     * @param prefix 生成序列号的前缀
     * @return
     */
    @RequestMapping(value = "/getIdByprefix/{prefix}", method = RequestMethod.GET)
    public String getIncre(@PathVariable("prefix") String prefix) {
        String format = new SimpleDateFormat("YYYY-MM-dd").format(new Date());
        String date = format.replaceAll("-", "").substring(2);

        //序列号前缀加特定标识，如系统模块名之类的 防止重复
        String key = prefix + date;
        String increResult = null;
        try {
            //如果该key不存在 会自动创建，值为第二个参数delta
            //最终调用的还是jedis的incrBy(byte[] key, long value)方法
            Long increNum = redisTemplate.opsForValue().increment(key, 1);
            if (!redisTemplate.hasKey(key)){
                redisTemplate.expire(key,1,TimeUnit.DAYS);
            }
            //不足补位
            increResult = prefix + date + String.format("%1$012d", increNum);
        } catch (Exception e) {
            System.out.println(e.getStackTrace());
            /*这里可以根据需求手动生成一个不重复的单号，
             * */
        }
        System.out.println(key+"---"+increResult);
        return increResult;
    }

    /**
     * 获取递增的序列号
     *
     * @param prefix 生成序列号的前缀
     * @return
     */
    @RequestMapping(value = "/getIdByRedis/{prefix}", method = RequestMethod.GET)
    public String getIncreID(@PathVariable("prefix") String prefix) {
        String dateFormat = new SimpleDateFormat("YYYY-MM-dd").format(new Date());
        String date = dateFormat.replaceAll("-", "").substring(2);
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(prefix + date, redisTemplate.getConnectionFactory());
        if (!redisTemplate.hasKey(prefix)) {
            //TimeUnit.DAYS：每天重置一次，这里就达到了我们想要的每天编号从0开始
            entityIdCounter.expire(1, TimeUnit.DAYS);
        }
        // incrementAndGet：自增+1然后返回。
        Long counter = entityIdCounter.incrementAndGet();
        //DecimalFormat：把数字格式化为固定位数
        DecimalFormat format = new DecimalFormat("000000000000");
        String Id = prefix + date + format.format(counter);
        System.out.println(Id);
        return Id;
    }

    @RequestMapping(value = "/getIncrIdByTenantId/{tenantId}", method = RequestMethod.GET)
    public void getIncrIdByTenantId(@PathVariable("tenantId") String tenantId) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors() + 1,
                20, TimeUnit.SECONDS, new LinkedBlockingQueue(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 100000; i++) {
            threadPoolExecutor.execute(() -> {
                idGeneratorFactory.getIdTest("a2d1");
            });
        }
    }

    @RequestMapping(value = "/getIncrId/{tenantId}", method = RequestMethod.GET)
    public void getIncrId(@PathVariable("tenantId") String tenantId) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors() + 1,
                20, TimeUnit.MINUTES, new LinkedBlockingQueue(256), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 100000; i++) {
            threadPoolExecutor.execute(() -> {
                idGeneratorFactory.getIdTest("et56");
            });
        }
        // idGeneratorFactory.getIdIncr(tenantId);
    }

}
